package vtc;

import java.util.concurrent.*;
import java.io.*;
import java.util.*;
import java.lang.*;

import sun.misc.Queue;

class VtcArrayBlockingQueue
{
	private ArrayBlockingQueue<VtcTimeTaggedEvent> queue_;
	
	public VtcArrayBlockingQueue(Integer length)
	{
		queue_ = new ArrayBlockingQueue<VtcTimeTaggedEvent>(length);
	}
	
	public void setQueue(ArrayBlockingQueue<VtcTimeTaggedEvent> queue)
	{
		queue_ = queue;
	}
	public ArrayBlockingQueue<VtcTimeTaggedEvent> getQueue()
	{
		return queue_;
	}
	
	synchronized public void forcePut(VtcTimeTaggedEvent event) throws InterruptedException
	{
		try
		{
			if(queue_.remainingCapacity() == 0)
				queue_.poll();
			queue_.put(event);
		}
		catch(InterruptedException e)
		{
			System.out.print("Interrupted during VtcArrayBlockingQueue::forcePut() method");
			throw e;
		}
	}
	
	VtcTimeTaggedEvent take() throws InterruptedException
	{
		VtcTimeTaggedEvent inEvent;
		try
		{
			inEvent = queue_.take();
		}
		catch(InterruptedException e)
		{
			System.out.print("Interrupted during VtcArrayBlockingQueue::take() method");
			throw e;
		}
		return inEvent;
	}
	
	synchronized VtcTimeTaggedEvent synchronizedTake() throws InterruptedException
	{
		VtcTimeTaggedEvent inEvent;
		try
		{
			inEvent = queue_.take();
		}
		catch(InterruptedException e)
		{
			System.out.print("Interrupted during VtcArrayBlockingQueue::take() method");
			throw e;
		}
		return inEvent;
	}
	
	synchronized Date[] getLastTimeTags(Integer n)
	{
		Integer numberOfCurrentEvents = queue_.size();
		Integer numberOfEventsToGet = n;
		
		Date[] dateVector;
		
		if(numberOfCurrentEvents < n)
			numberOfEventsToGet = numberOfCurrentEvents;
		
		dateVector = new Date[numberOfEventsToGet];
		
		Iterator<VtcTimeTaggedEvent> iter = queue_.iterator();
		
		for(int i = numberOfEventsToGet-1; i >= 0; i--)
		{
			Date d = iter.next().getTimeTag();
			dateVector[i] = d;
		}
			
		return dateVector;
	}
	
	synchronized Object[] getLastEvents(Integer n)
	{
		Integer numberOfCurrentEvents = queue_.size();
		Integer numberOfEventsToGet = n;
		
		Object[] objectVector;
		
		if(numberOfCurrentEvents < n)
			numberOfEventsToGet = numberOfCurrentEvents;
		
		objectVector = new Object[numberOfEventsToGet];
		
		Iterator<VtcTimeTaggedEvent> iter = queue_.iterator();
		
		for(int i = numberOfEventsToGet-1; i >= 0; i--)
		{
			Object o = iter.next().getEvent();
			objectVector[i] = o;
		}
			
		return objectVector;
	}
	
	synchronized Object[] getLastEventsLastTimeTag(Integer n, Date timeTag)
	{
		Integer numberOfCurrentEvents = queue_.size();
		Integer numberOfEventsToGet = n;
		
		Object[] objectVector;
		
		if(numberOfCurrentEvents < n)
			numberOfEventsToGet = numberOfCurrentEvents;
		
		objectVector = new Object[numberOfEventsToGet];
		
		Iterator<VtcTimeTaggedEvent> iter = queue_.iterator();
		VtcTimeTaggedEvent current;
		for(int i = numberOfEventsToGet-1; i >= 0; i--)
		{
			current = iter.next();
			Object o = current.getEvent();
			objectVector[i] = o;
			timeTag = current.getTimeTag();
		}
			
		return objectVector;
	}
	
	synchronized VtcTimeTaggedEvent[] getOldestEvents(Integer n, boolean inverted)
	{
		Integer events2get = n;
		Object[] allEventObjects = queue_.toArray();
		VtcTimeTaggedEvent[] allEvents = new VtcTimeTaggedEvent[allEventObjects.length];
		//System.out.print("-----------------------------------------------\n");
		for(int i = 0; i < allEventObjects.length; i++)
		{
			allEvents[i] = (VtcTimeTaggedEvent)allEventObjects[i];
			//System.out.print("date: " + allEvents[i].getTimeTag().toString() + "\n");
		}
		
		if(allEvents.length < n)
		{
			events2get = allEvents.length; 
		}
		VtcTimeTaggedEvent[] events = new VtcTimeTaggedEvent[events2get];
		for(int i = 0; i < events2get; i++)
		{
			events[i] = allEvents[i];
			//System.out.print("date2: " + events[i].getTimeTag().toString() + "\n");
		}
		if(inverted)
		{
		 	events = invert(events);
		}
		return events;
	}
	
	synchronized VtcTimeTaggedEvent[] getNewestEvents(Integer n, boolean inverted)
	{
		Integer events2get = n;
		Object[] allEventObjects = queue_.toArray();
		VtcTimeTaggedEvent[] allEvents = new VtcTimeTaggedEvent[allEventObjects.length]; 
		//System.out.print("-----------------------------------------------\n");
		for(int i = 0; i < allEventObjects.length; i++)
		{
			allEvents[i] = (VtcTimeTaggedEvent)allEventObjects[i];
			//System.out.print("date: " + allEvents[i].getTimeTag().toString() + "\n");
		}
		
		if(allEvents.length < n)
		{
			events2get = allEvents.length; 
		}
		
		VtcTimeTaggedEvent[] events = new VtcTimeTaggedEvent[events2get];
		//System.out.print("-----------------------------------------------\n");
		for(int i = 0; i < events2get; i++)
		{
			events[i] = allEvents[allEvents.length - events2get + i];
			//System.out.print("date2: " + events[i].getTimeTag().toString() + "\n");
		}
		
		if(inverted)
			{
			 	events = invert(events);
			}
		return events;	
	}
	
	VtcTimeTaggedEvent[] invert(VtcTimeTaggedEvent[] events)
	{
		Integer size = events.length;
		VtcTimeTaggedEvent[] invertedEvents = new VtcTimeTaggedEvent[size];
		for(int i=0; i<size; i++)
		{
			invertedEvents[size-1-i] = events[i];
		}	
		return invertedEvents;
	}	

	boolean isEmpty()
	{
		return queue_.isEmpty();
	}

}